메뉴 바로가기 검색 및 카테고리 바로가기 본문 바로가기

한빛출판네트워크

IT/모바일

이아스님이 제공하는 자바 헤드라인(9월 24 ~ 30일)

한빛미디어

|

2001-10-06

|

by HANBIT

8,632

2001년 9월 30일 일요일 선호 설정(preferences)은 J2SE 1.4 멀린에 새로이 들어갈 API중의 하나입니다. 멀린 FCS 시점이 멀지않아서인지 최종 제안 초안이 나왔습니다. 잠깐 저 프레퍼런스의 뜻을 조금 자세하게 살펴보지요. 모든 애플리케이션에는 사용자(혹은 개발자)가 설정할 수 있는 선택 사항이 있습니다. 예를 들어 텍스트 에디터라면 백업 파일을 만들 것인지, 또 폰트는 뭘 주로 쓸 것인지... 이런 것에 대해서 애플리케이션은 기본적인 설정을 최초에 제시합니다. 이것을 기본 설정(defaults-default settings, 디폴트는 원래 "무엇을 아직 하지 않았다"는 뉘앙스를 가지고 있습니다. 즉 사용자가 아직 자신이 원하는 설정을 하지 않은 상태라는 표현)이라고들 부르지요. 그래서 대체로 애플리케이션들은 이런 설정을 바꿀 수 있도록 선택사항(options)이라는 메뉴를 넣었었는데 최근 이것이 선호 설정(preferences)로 용어가 바꾸어가고 있는 추세입니다. 그런 이유는, 옵션이 마치 (없는) 뭔가를 추가한다는 듯한 (오해의 소지가 있는) 냄새를 풍기는 반면, 프레퍼런스는 디폴트를 자신이 좋아하는 식으로 바꾼다는 느낌이 들기 때문이라고 여겨지는군요. 그래서 기본 설정(defaults, 사용자가 건드리기 전) → 선호 설정(preferences, 사용자가 건드린 후) 물론 기본 설정으로 돌아갈 수 있는 원상복구(reset)기능도 애플리케이션마다 빼먹지 않고 있습니다. 현재는 기본 설정을 포함하여 사용자가 접근 가능한 변경 사항 일체를 선호 설정-프레퍼런스로 부르고 있습니다. 자바에서는 이러한 사안에 대해서 이전부터 Properties라는 객체를 제공하여 편의성을 높여왔었는데, 이 객체가 설계한지가 꽤 되었고, 그사이의 선호 설정 분야는 무섭고도 방대하게 발전하여 자바 애플리케이션을 만드는 개발자들의 개선-강화된 API의 요구가 거세었는지 이번에 아예 일대쇄신을 통해 API가 새로 나왔는데 바로 그것이 프레퍼런스 API입니다. 선호 설정 관련 JSR페이지에 가보면 최근까지의 명세와 예제까지 풍부하게 담겨 있습니다. 멀린의 새로운 기능을 미리 숙지하고 싶으신 분들에게는 무척 추천하고픈 항목입니다. 당신이 짠 J2EE 애플리케이션은 얼마나 성능이 뛰어나며, 얼마나 확장성이 좋습니까? 이런 질문에 답하기 위해서는 우선 평가의 기준과 수단이 있어야겠죠. 자바 커뮤니티 프로세스 프로그램(Java Community Process Program-JCP에서 실시하는 API나 기술의 명세에 대한 연구와 합의뿐만 아니라 업계에 실제적인 도움을 주고자 마련한 기획 일체)에서 제시하는 ECperf가 명세 1.0과 함께 실제 도구도 업데이트했습니다. EJB 컴포넌트(백엔드), JSP화면(프론트엔드)에 실행 규칙을 구현하고 사용자 부하를 시뮬레이션할 환경까지 제공하는 ECperf는 그동안 변변한 벤치마크 도구가 없어 "정말 잘 짜고 있는 건지..." 하는 회의에 불안한 J2EE 개발자와 학습자에게 모두 도움이 되리라 믿습니다. 특히 XP(이 약어를 처음 보시는 분은 28일 소식을 참고하세요)와 관련하여 거의 실시간에 가까운 테스트 코드 작성에도 편의성을 제공하여 건강한 애플리케이션 개발에도 일조하지 않을까 싶군요. 2001년 9월 29일 토요일 생명정보학(bioinformatics)이란 말을 들어보셨는지요. 최근의 인간 유전자 지도에 대한 관심이 높아지면서 21세기를 이끌어갈 첨단 기술로 불리는 생명공학(biotechnology)와 컴퓨터가 만나 이루어진 융합 학문(fusion field)입니다. 이미 널리 알려진대로 유전자의 특성을 잡아내기 위해서는 무수한 패턴 인식(Pattern Recognition) 작업을 실시해야하는데, 바쁘게 내달리는 컴퓨터 기술이 생명공학의 발전에 많은 기여를 해왔습니다. 저도 일전에 유전자의 염기 정보를 100차원 벡터로 늘여서 100개의 유전자(즉 100개의 벡터)에 대한 특성 추출을 수행하는 자바 프로그램(코드명 레이스톰(RayStorm))에 대한 연구를 했던 적이 있었는데, 이미 미국의 유수 대학과 연구소에서 이와 비슷한 작업을 생명정보학이나 계산 생물학(computational biology)이라는 이름으로 학문화해가고 있습니다. 그렇다면 이러한 유전자 정보 처리와 자바와는 어떤 고리가 있을까요? 썬의 자바 사이트에 실린 글을 보면 대강의 감을 잡을 수 있습니다. 다소 전문적인 내용도 들어있기는 하지만, 요약정리하자면, "자바의 간단(simplified)하면서도 유연한(flexible) 코드 스타일은 아주 범용적(generic)이다. 생물학이 다루는 소재는 변화무쌍하고 심지어 변덕이 죽끓듯하다고 해도 과언이 아니다. 따라서 유기적으로 발전하는(organically evolved) 자바 기술의 범용성은 생명공학의 그것과 아주 흡사하다." "특히 눈에 잘 보이지 않는 정보를 시각화(Visualize)한다는 측면에서 자바의 GUI관련 기술, 즉 Swing, Java2D, Java3D, Java Advanced Imaging는 객체지향적이며 동시에 적절하고 신속한 정보 표현 수단으로 잠재성을 지니고 있다." 제가 짰던 레이스톰도 오로지 숫자로만 넘어온 유전자 관련 정보를 RGB값으로 변환하여 칼라풀하게 표현하면서 패턴을 인식하는 방식을 취하고 있었습니다. 물론 그러한 색공간 변환이 실제 유전자의 특성에 변화를 주지않는(invariant)다는 가정아래서 벌어진 일이지만, 눈으로 보아야 안심하고 확신하는 인간에게는 피할 수 없는 과정입니다. 앞으로도 자바는 IT분야안에서 열심히 줄기와 가지를 뻗어나가겠지만, 다른 분야와의 연계도 상당한 폭발력을 내재하고 있습니다. 특히 생명공학과의 합작은 이상적인 "드림 팀"일지도 모르지요. 이런 상상을 해봅니다. 자바 객체가 유전자와 그를 바탕으로 이루어진 생명체를 나타내고, 그 객체들을 성장 컨테이너에 담아 유전자 분석과 생체 배양을 시뮬레이션할 수 있다면... 자바 객체가 실제 생명의 객체와 대응한다니, 장자처럼 "내가 객체인지 객체가 나인지" 모를 아스트랄한 메트릭스의 세계가 곧 오지 않을까요? 아주 발 빠르게 기술을 전파하고 있는 록스(Wrox) 출판사에서 이번에는 아직 FCS를 내지도 않는 JDK 1.4의 기술을 소개하는 "Early Adopter J2SE 1.4"라는 묘한 이름의 책을 발표했습니다. 고맙게도 맛뵈기 챕터가 2개나 올라와 있군요. 우선 썬의 책 소개 글에서 사전 정보를 얻으시고 관심있으시면 10월 구입을 생각해보세요. 이제 J2SE 1.4 일명 멀린이 막바지에 이르렀는데, 벌써 1.5인 타이거(Tiger) 얘기가 나오네요. 아마 타이거에 들어가지 않을까 싶은 기능(이라고 하기엔 너무나도 혁신적인 개념)인 범용성(Generics-JSR14에서 논의중)를 소개하고자 합니다. 정확히는 범용형(汎用型, Generic Type)의 도입을 뜻하는 범용성은 한 소개 문구에 의하면 "자바에 C++수준의 난이도를 처음으로 받아들이는 일대 사건" 이 될지도 모른다고 합니다. 현재 원형(Prototype)을 다운로드받을 수 있어 테스트할 수 있는데, 원형 구현안에는 다음과 같은 예제가 있습니다.
import java.util.LinkedList;
import java.util.Collections;

class Test 
{
public static void main(String[] args) 
{
 // Integer list
 LinkedList xs = new LinkedList();
 xs.add(new Integer(0)); xs.add(new Integer(1));
 Integer x = xs.iterator().next();
 Integer mb = Collections.max(xs);
    
 // for output, this part is not included in the original version.
 System.out.println(x); 
 System.out.println(mb);

 // string list
 LinkedList ys = new LinkedList();
 ys.add("zero"); ys.add("one");
 String y = ys.iterator().next();

 // for output, this part is not included in the original version.
 System.out.println(y);

 // string list list
 LinkedList> zss 
   = new LinkedList>();
 zss.add(ys); 
 String z = zss.iterator().next().iterator().next();
     
 // for output, this part is not included in the original version.
 System.out.println(z);
 }
}
아마 그냥 보기만해도 희한한 부분이 보일 것입니다. 바로 LinkedList, LinkedList처럼 콜렉션 클래스에 <클래스>를 붙이는 문법입니다. 우선 이 예제를 컴파일해보기 위해서는 다음과 같은 도스 명령을 실행해야합니다. e:₩jdk1.3.1₩bin₩javac -J-Xbootclasspath/p:e:/tools/jsr14_adding_generics-1_0-ea/javac.jar -bootclasspath e:/tools/jsr14_adding_generics-1_0-ea/collect.jar;e:/jdk1.3.1/jre/lib/rt.jar Test.java (단 JDK 1.3.1이 e:₩jdk1.3.1에 깔려있고, 아까 받은 범용성 원형을 e:₩tools에 풀었다고 가정하면) 아주 복잡하기는 하지만 비교적 컴파일은 에러없이 잘 됩니다. 결과도 뭐 당연하게 0 1 zero zero 로 나오지요. 가장 궁금한 것은 과연 LinkedList xs = new LinkedList(); 와 같은 문법이 무슨 뜻이냐는 겁니다. 단도직입적으로 말하면 이는 LinkedList에 들어갈 Object형을 Integer형으로 제한한다는 의미입니다. 따라서 그 아래 문장들을 보면
xs.add(new Integer(0));  
이건 보통 콜렉션에서도 당연한 것이지만(add 메쏘드의 인수형이 Object이므로 Integer도 당연히 들어갈 수 있습니다.)
Integer x = xs.iterator().next(); 
는 잘 보면 당연하지 않다는 것을 알 수 있습니다. 왜냐면 현 자바 콜렉션에서는 xs.iterator().next()의 반환형(return type)이 Object이기 때문이죠. 따라서 지금까지는
Integer x = (Integer)xs.iterator().next(); 
와 같이 명시적 섭외(explicit casting)을 반드시 해야합니다만, 범용성의 도입으로 이 과정이 사라지게 된 셈이지요. 그렇다면
LinkedList ys = new LinkedList(); 
도 마찬가지로 집합(collection)안의 원소(element)객체는 String만 들어가고 String만 나온다는 뜻입니다. 여기서 주목할 점은 범용성으로 선언된 xs나 ys가 Object를 다루는 LinkedList에서 파생된 새로운 집합체라는 것입니다. 즉 LinkedList를 Object객체가 들어가고 나오게만 설계하면, 범용형은 거기에 우리가 원하는 형만 들어가고 나가게 알아서 만들어준다는 참으로 기묘한 발상이지요. 이런 방식을 구상하게 된 까닭은 어디에 있을까요? 자바가 대중화되는 데에 혁혁한 공을 세웠던 자바 콜렉션은 프로그래밍의 영역에서 자료의 군집이 얼마나 빈빈하게 다루어지는가를 여실이 보여주었습니다. 그런데 문제는 자바 콜렉션 자체가 상당히 아리까리하게 되어 있어 많은 사용자들을 디버그의 노동과 개념의 혼동으로 몰아넣었다는 거지요. 자바 콜렉션의 가장 심오한 특징은 이종성(異種性, heterogeneity)으로서, 서로 다른 자료형의 객체를 마음것 섞어 집어넣을 수 있는 (heterogeneous는 잡종이라는 뜻도 있음) 특권이 있습니다. 예를 들어
Vector a = new Vector():
a.add(new Integer(1));
a.add("IAS"); 
하지만 실제 세계에서 이런 혼성 집합은 거의 쓸 일이 없고, 대체로 일정한 종류의 객체가 들어가는 동종성(同種性, homogeneity)을 유지하게 됩니다.
Vector a = new Vector();
a.add("IAS");
a.add("CB"); 
결국 순종만 키우면 당연이 순종밖에 안나오는데도,
String b = (String)a.elementAt(0); 
과 같이 마치 순종이 아니었던 것을 순종화하는 불필요한(redundant) 작업-명시적 섭외가 꼭 끼었던 것입니다. 자바의 배열은 동종성을 타고나기때문에
String[] a = new String[10]; 
a에는 무조건 String만 들어가야하지만, 자바 콜렉션들은 이종성을 바탕으로 하고 있기에 그렇지 못했습니다. 또한 콜렉션마다 모든 객체형만을 주고받도록 고안한다면 엄청나게 많은 변형을 양산할 것이고 사실상 "아니될 일"이 되고 말지요. 그래서 나온 것이 콜렉션마다 특정형(specific type)으로 한정할 수 있는 범용형(generic type)입니다.
generic -> specific 
그러면 특정형이라고 말하지 왜 범용형이라고 말하는가? 이부분이 서구 과학 문명의 교묘한 점입니다. 자바의 범용형으로 예를 들면, "범용형이란 특정형의 상위 개념(meta concept)이다. 즉 Integer, String등의 무수한 자바 클래스 레퍼런스 자료형 하나하나가 특정형이라면, 그것들을 모두 포괄한 개념, 즉 어떤 자바 클래스 레퍼런스 자료형도 적용시킬 수 있다라는 뜻을 뒤로 깔고 있는 것이 바로 범용형이다." 즉 범용형이라는 말은 Integer나 String과 같은 특정형을 말하는 것이 아닙니다. 오히려 "어떤 형인지는 모르지만 아무튼 어떤 형이든 커버한다."라는 능력(capability)를 상징하는 용어라고 보면 적절할 듯 싶습니다. 여러분은 어떻게 생각하시는지요? 자바에 이렇게 새로운, 하지만 자칫 잘못하면 이전 방식과의 혼동을 초래할 수 있는 문법의 도입에 대해서. 범용성은 단순히 API차원의 지원뿐만 아니라 자바 언어 사양 자체를 바꾸는 작업이기때문에 급하게 J2SE 1.4에는 포함되지 않은 것 같습니다. 좀 더 신중하게 검토하고 많은 개발자들의 의견들 수렴한 후 J2SE 1.5인 타이거에 수록될 지의 여부가 판가름 날 전망입니다. 아직 나오지는 않았지만 록스의 다른 책도 소개하지요. "Early Adopter Mac OS X Java"라는 제목으로 아직 구체적인 책의 구성을 알려지지 않았지만, 애플에서 공식적이며 적극적으로 지원하는 자바 기술이라는 측면에서 맥오에스텐의 자바는 높히 살만 합니다. 더우기 맥오에스텐용 애플리케이션의 개발 표준 언어로서로 자리매김을 하고 있어 단순히 "자바가 된다"정도가 아니라 "자바로 한다"가 가능하니까, 이 책에서 그러한 실용적인 예제와 대안 제시가 두드러지지 않을까 추측해봅니다. 2001년 9월 28일 금요일 JNI(Java Native Interface)는 자바인이라면 경외에 마지않는 분야입니다. 자바 기술이 발전해오면서 점점 도외시하면 면도 없지 않지만요. (제가 최근에 읽고 있는 Effective Java Programming Languange Guide의 7장 36항목에는 이렇게까지 나와있지요. "성능 향상을 목적으로한 JDK 1.3이상에서의 JNI 사용은 거의 권하고 싶지 않다." 라고 밝히고 있다. 그만큼 JDK 1.3이후로 충분히 기본 동작의 최적화를 이루었다는 자신감의 피로(披露)인 셈) 아무튼 어떤 분이 JNI를 통해 C 함수를 호출했더니 다음과 같은 에러를 만났다고 합니다. EXCEPTION_STACK_OVERFLOW 음... 언젠가 JVM(java 명령)의 옵션중에 스택에 관련된 것을 본 기억이 나서 자바 문서를 죽어라고 찾았지만 이상하게도 없더군요. 근데, 이게 썬 솔라리스(Sun Solaris)나 리눅스용 java에는 있습니다. -Xss숫자 묘하게도 이 옵션이 윈도우즈용 java에는 빠졌는데, 사실은 유효하다고 합니다. 이는 JDK 1.3에서의 얘기이고 재밌는 것은 여기 이 문제와 관련된 버그 리포트 문서를 보면 JDK 1.2.2에서는 EXCEPTION_STACK_OVERFLOW가 안나던 것이 JDK 1.3에서는 났다고 합니다. 아무튼 결론부터 말하면 -Xss로 자바가 C함수를 호출할 때 그 함수가 쓸 스택 메모리를 충분히 할당해주면 해결된다는군요. 예를 들어, java -Xss1024k 어쩌구저쩌구... (1024k = 1024킬로바이트, 즉 1메가바이트) 자신이 호출하는 함수에 따라 적절히 임계치를 찾아 설정해주면 문제는 풀리며 이는 버그가 아니라고 썬은 주장하지만 이 버그(?)를 경험한 사람들은 JDK 1.2.2에서는 일어나지 않았다며 엄연히 JDK 1.3의 버그라고 주장하고 있답니다. 이런 상황은 "업그레이드 신화"에 일침을 가하는 경우가 아닌가 싶습니다. 우리는 업그레이드하면 무조건 모든 것이 다 나아지는 것으로 생각하는데, 물론 나아지는 점도 있지만(많지만) 늘쌍 하는 말로 트레이드오프(trade-off)가 있다보니 없던 버그도 생기나봅니다. 업그레이드는 대체로 신규 기능 추가와 기존 기능 강화로 이어지기 때문에 애플리케이션 자체의 덩치가 커지지 않을 수 없습니다. MS 오피스의 경우만 봐도 그렇죠. 문제는 이렇게 늘어나는 개발 실적물속에서 어떻께 품질을 유지(향상은 꿈도 못꾸고)하냐는 것입니다. 이에 대해 XP(eXtreme Programming)의 태두 켄트 벡은 테스트(test)의 역할을 강조합니다. 최소 단위 기능부터 쌓아올라가는 절처한 테스트는 기존 프로그램 개발시에 보여주는 "바닥치고 에러 많아지기" 현상(어느 시점에는 거의 없다가 나중에 기하급수적으로 늘어난다.)을 해결할 수 있다고는 하는데... 조만간 JUnit라는 자바 테스트 도구를 소개하여 이 주제로 자세히 얘기해보죠. 2001년 9월 27일 목요일 자바 3D의 활용을 보여주는 Java3D Fly Through(FT)가 베타를 뗏습니다. 그동안 자바 3D의 본격적인 예제 부족에 목말라하던 많은 3D 애호가들에게 뭔가 실낱같은 희망을 주어왔던 FT는, 역으로 자바 3D가 아직까지 강력한 임팩트로 세상을 흔들지 못하고 있다는 현실을 암시하고 있습니다. "플라이 쓰루"라는 이름 자체가 뜻하듯이 자바 3D가 날아오르기를 바라고는 있지만,
  1. 자바 3D 자체가 J2SE에 기반하고 있어서 웹 3D의 대세로 나서기에는 선결 조건이 많고,
  2. 설사 J2SE가 SDK든 RE(Runtime Environment)로든 깔려있다고 해도 자바 3D 설치가 필요하고,
  3. 결정적으로 자바 3D가 느리고 많은 양의 그래픽 처리를 견디지 못한다
는 치명적인 단점으로 발만 동동 구르고 있습니다. 그래서 그런지 자바 3D 사이트에 가보면 실제로 자바 3D를 쓰고 있는 서비스들을 소개하며 "절대 자바 3D는 못쓸 것이 아니다."라고 역설하고 있습니다. 하지만 실려있는 사이트들의 면면을 살펴보면, 대중적이며 범용적이라기보다는 특화된 인트라넷 분야에서 그럭저럭 적용되고 있음이 느껴집니다. 이런 이유는 바로 위에서 지적된 단점들을 그나마 전문적, 제한적 용도가 희석시키기 때문이겠죠. 따라서 대중화의 길목에는 다음과 같은 관문들이 버티고 있습니다.
  1. 자바 실행 환경의 확대
  2. 3D 가속 환경의 보급
  3. 자바 3D 구현의 최적화-(어쩔 수 없이 윈도우즈 운영체계에서는 다이렉트X와의 협업등)
  4. 설치 과정의 간소화(플러긴 형식)
역시 클라이언트 시장에서는 늘 썬은 MS와 어떻게든 "적과의 동침"을 하지 않을 수가 없습니다. 부디 자바 3D만큼은 2D같이 최적화에 오랜 시간이 걸리자 않았으면 좋겠네요. 자바의 범용 보안 서비스(Generic Security Service-GSS) API 버전 2가 최종 권고안 1.0으로 공개되었습니다. GSS API는 개발 언어와 실행 플랫폼에 독립적인 보안 애플리케이션 개발을 위해 마련된 기술로서 현재 RFC2743으로 논의중이고 자바쪽 바인딩(binding)은 RFC2853으로 개진중입니다. 조만간 J2SE에 통합하는 식으로 구현되지 않을까 내다보고 있습니다. 점차 보안 영역에 강화를 꿈꾸는 J2SE는 이미 SDK 1.4에서 JCE(Java Cryptography Extension), JSSE(Java Secured Socket Extension), JAAS(Java Authentication and Authorization Service)를 합체한 이력이 있습니다. 이는 J2EE에서의 실제적인 필요성과 동시에 J2ME에서의 축소 적용에서도 유리한 고지를 점령하려는 썬의 자바 정책중의 일완으로 추측됩니다. 자바 GSS 바인딩은 이러한 자바 보안 시스템의 범용성을 높히는 역할로 자리잡을 것입니다. 자바의 대분류 API군중에 제인(JAIN) 이라는 것이 있습니다. 지니(JINI), 지로(JIRO)와 함께 자바 기반 확장 기술로는 상당히 큰 분야인데, 기본적으로 전신, 전화, 라디오-텔레비전 등에 의한 원격 통신(telecommunication) 기술의 자바적 접근이라고 보면 두리뭉실 맞습니다. 이렇게 광범위한 영역을 다루다보니 API도 여러분과가 생기기 마련인데, 크게 프로토콜 API와 애플리케이션 API로 나뉘고 프로토콜 API안에서도 ISDN 용, 모바일(Mobile) 용등 다양하고, 애플리케이션 API도 이들 프로토콜을 기반으로 행할 트랜잭션 구현에 관련하여 많은 가지를 치고 있습니다. 현재 모두 JCP에서 논의중에 있으며 최근 가장 주목받고 있는 이동통신 분야에 해당하는 MAP(Mobile Application Part) API가 1.0 첫 일반 공개 명세(Public Release Spec.) 1.0ISUP(ISDN User Part) API 0.7 공개 검토 초안(Public Review Draft)을 각각 내놓았고, TCAP(Transaction Capability Application Part)와 OAM(Operations, Administrations, & Maintenance) 1.0은 썬의 라이센스 동의아래 참고 구현체(Reference Implementation)과 기술 호환성 검사기(Technology Compatibility Kits)를 제인 사이트를 통해 받아볼 수 있습니다. 아직 발아기에 있지만 충분한 잠재성을 지니고 있는 기술 제인, 아무도 서블릿과 JSP가 이렇게까지 클 줄을 몰랐다면, 그녀의 가능성, 어떻게 생각하시는지요? 2001년 9월 26일 수요일 미국의 정세 변화에도 흔들리지 않고 애플의 맥오에스(MacOS) 10.1 이 약속대로 9월에 발표되었습니다. MacOS X이후 퍼포먼스에 대한 지적과 대단위 버그 색출의 결과로 보여지는 이번 메이저급 업그레이드는, 그러나 기대와는 달리 한글, 중국어를 비롯한 제 2 언어권(애플의 구분 개념-제 1 언어권에는 영어와 일본어등)의 OS차원의 기본 지원이 빠졌습니다. 유니코드에 기반한 강력한 다국어 지원 기능을 자랑으로 하는 맥오에스로서는 다소 실망스럽군요. 또다시 한글화 작업때까지 기다려야 하겠습니다. 언제쯤 로케일 없이 유니코드 기반 국제화-리소스 기반 지역화가 완벽한 운영체계와 애플리케이션의 세상이 올까요. 각개격파식의 MS마케팅 방식에서는 기대하기 어려운데, 애플에게는 좀 더 범세계적인 운영 방식을 기대해봅니다. 일본의 아이아플리(핸드폰용 자바 애플리케이션) 개발용 에뮬레이터로 가장 폭넓은 인기를 누리고 있는 아이-제이드(i-JADE) 가 1.3이라는 안정적인 버전으로 업그레이드되었습니다. 사실 바로 그전 버전에 치명적인 버그인 IApplication.getSourceURL()의 이상한 반환값(파일 URL이 나온다. 실제로 당한 사람은 아주 짜증냄)을 고치고 기타 자질구레한 것들도 싹 고쳤다고 합니다. 아이-제이드는 무료입니다. 물론 유료판도 있지만, 이 무료라는 사실이 아이-제이드가 아이아플리 에뮬레이터 시장을 장악하게 된 가장 큰 비결이 아닐까 싶습니다. 물론 매달 꾸준히 업그레이드하는 제작사의 성의도 무시할 수 없지요. 가끔 유료판을 사주고 싶을 정도로 고마운 프로그램입니다. 이렇게 자연스럽게 구매를 유도하는 은근함에 칭찬을 해주고 싶습니다. 물론 아이-제이드만으로 아이아플리를 개발할 수는 없습니다. 제가 가장 편하게 즐기고 있는 환경은 JDK 1.3.1 + Forte for Java 2.0 + J2ME Wireless SDK for the DoJa 2.2 + i-JADE 1.3 입니다. 순서대로 깔면 복이 오지요. 특히 도자(DoJa) 설치시에는 포르테 애드 온을 꼭 선택하세요. 포르테에서 빌드가 즐거워집니다. 거기에 아이-제이드의 클래스 JAR파일을 풀어서 주 실행 클래스를 com.zentek.jam.Jam으로 맞춰놓고 실행 인자로 개발중인 아이아플리의 JAM파일을 지정해주면 CTRL+ALT+F6로 컴파일-사전검증(preverify)-JAR 생성-실행까지 한 큐에 됩니다. 한번 쓰면 그 엄청난 편리함에 다른 툴을 거의 못쓸 정도로... (중독성이 강하지요.) J2EE SDK 1.3, J2SE SDK 1.3.1, 그리고 J2ME WK(Wireless Toolkit) 1.0.3 베타의 3위 일체 개발 환경을 활용하는 예제인 썬의 스마트 티켓(SmartTicket) 1.0 베타가 등장했습니다. 이미 스마트 티켓은 소개되었는데, 이번 엔터프라이즈측의 대단위 업그레이드에 발맞춰 일단의 쇄신을 이루었습니다. 곧 J2SE SDK가 1.4, 그리고 J2ME WK도 베타를 벗는다면, J2EE SDK 1.3 + J2SE SDK 1.4 + J2ME WK 1.0.3 의 환상적인 만남이 이루어지겠군요. (여기에 포르테 3.0 휠마우스 지원 버전까지 하면... 공짜도 상용 부럽지 않겠다...) 각설하고 소스와 설계도면까지 제시되어 J2EE 백엔드 서버 + J2SE 개발 환경 & JVM + J2ME 프론트엔드 클라이언트 시스템의 고갱이를 맛볼 수 있습니다. 이런 체제를 구축하고 싶어도 어찌해야할지 감이 안오시는 분들에게는 좋은 예제가 되리라 믿습니다. 2001년 9월 25일 화요일 어제 JAI를 쓰고 보니 소리소문없이 JAI 1.1 FCS가 나왔더군요. 핑 인코딩 경쟁에서는 참패했지만, 이제 슬슬 이미지 I/O로서의 기능보다는 여러가지 자바 2D가 해내지못하는 이미지 처리 기능을 제공하는 방향으로 가닥을 잡고 나아가는 모습입니다. 특이할 만한 사항은 이번 FCS가 JAI API 스펙 자체도 1.1 FCS를 구현한 것은 아니고, JAI API 1.1 공공 검토 초안(Public Review Draft)을 바탕으로 한 것이라는 사실입니다. 아무래도 JSR의 진척은 더딘데 반해 필드의 요구는 거세서 어느 정도 자리잡은 API를 구현한 것이 아닌가 짐작이 가는군요. 일본의 맥(Mac) 얘기를 잠깐 하려합니다. 지난 일요일 함께 일하는 디자이너 한분이 아이북(iBook)을 사셨습니다. 애플의 최신 엔트리 노트북 모델이지요. 가격 대 성능비가 탁월한 것으로 맥 사용자들사이에 널리 알려진 컴입니다. 근데 재밌는 것은 이분이 맥을 사기전에 이미 엄청난 사양의 피씨도 가지고 있다는 사실입니다. 대강 팬티엄4에 메모리도 256이상일 거라 짐작되는데, 이번에 산 아이북은 그정도는 아니지요. 도대체 무엇때문에 아이북을 샀을까요? "피씨가 있는 방과 티비가 있는 방은 달라서요, 티비 보면서 탁자에 놓고 피씨하려구요." 그래서 조그만(?) 노트북을 산 거군요. 아무튼 우리돈 약 200만원을 들여 맥을 산 것을 본 징꿍-일본 체류 4년차인 한국인 기획자-의 일갈. "이런 비효율적인 기계를 잘도 사주다니, 애플은 일본에게 감사해야 되." 아주 극단적으로 비꼬았지만 그렇다고 일리가 전혀 없는 말도 아니지요. 옛날에야 맥에서 되는 것이 피씨에서 안되는 것도 종종 있었지만, 요새는 그런 것도 없고(오히려 역전되었죠. 특히 게임들...), 같은 성능대 가격으로 보면 정말이지 "있는 사람"아니면 꿈도 꾸기 힘들어요. 그러나 일본인들은 죽으라고 삽니다. 그러니 그나마 싼 아이맥과 아이북이 각각 판매 1위를 달리는 것도 무리는 아닐 듯 싶네요. 그래서 이런 풍토의 결과 일본은 애플의 최고 관심국가가 되었습니다. 각종 오에스와 프로그램에 일본어 지원은 거의 즉각적으로 이루어지고 있고, 이건 지원의 차원이 아니라 최적화까지 되어있으니 기쁨 두 배 만족 열 배지요. 거기에 각종 일본 내 애플리케이션들도 맥 지원에 인색하지 않습니다. 이에 비하면 우리나라의 맥 현실은 처절하지요. 이런 얘기를 들었습니다. 맥은 10%의 인간을 위한 컴퓨터라고. 맥은 10%의 뭔가 튀고 싶고 다르고 싶은 본능적인 유전자를 지닌 사람들의 선택을 받은 컴퓨터라는군요. 어찌보면 더 비싸고 더 불편할지 몰라도, 그런 것을 감수하게 하는 매력에 끌리는 사람이 바로 전 인류의 10%라는, 황당하지만 그럴듯한 말이었습니다. (그래서 미국의 맥 시장 점유율이 10%대?) 그렇다고 맥 쓰는 사람이 무슨 용가리 통뼈라는 얘기는 아니구요, 개성과 선택을 중시하는 서구 개인주의 문화의 꽃중의 하나가 아닐까... 유독 맥이 힘을 못쓰는 우리나라는, 엘렉스 그리고 애플 코리아의 정책 실패뿐만 아니라 뭔가 근저한 원인이 있는 것이 아닐까... 여전히 줄대기와 따라가기에 집착할 수밖에 없는 현실이 10%는 고사하고 1%도 맥을 멀리하게 하는 은근한 압박이 아닐까... 맥오에스 10.1이 나오기만을 기다리는 답답한 마음에서 한 번 써보았습니다. 2001년 9월 24일 월요일 지난주 소식에 등장했던 JDK 1.3.1_01a를 설치한 후 포르테를 실행했더니 안뜨더군요. 다시 JDK 1.3.1_01을 깔았더니 잘 돌아가덥디다. 아무래도 a의 베타 버그인가 봅니다. 사용하시는 분들은 주의하세요. 쓰레드를 잘 아십니까? 저는 솔직히 잘 모릅니다. 이러고도 자바 입문서를 쓰려는 제 자신이 불쌍하군요. (예상되는 독자는 더 불쌍하고.) 아무튼 이러던 차에 한빛 네트웍에 쓰레드에 대한 논의글이 있어서 소개하려고 합니다. 저는 다 읽어보고 나서 번역문인줄 알았는데, 마지막에 참가자들의 면면을 보니 우리나라의 장한 개발자분들이셨습니다. 개진하는 내용의 심도가 정말로 심상치않아 스스로 부끄러움과 동시에 밝은 희망을 느꼈습니다. 특히 언어 전반에 대한 해박한 시선과 자바-C#간의 비교를 통한 쓰레드 구현의 이모저모를 실제 개발하고 계신 분들의 살아있는 감각으로 멋지게 파헤쳤습니다. 쓰레드를 잘 알고 싶으신 분들은 두려워마시고 찬찬히 읽어보십시다요~ (저랑 같이요~) 핑(PNG, PiNG)은 이제 인터넷의 표준으로 상당한 입지를 굳혀가고 있는 이미지 포멧입니다. 하지만 아직도 쥐프(GIF)의 잔재는 여기저기 남아있습니다. 널리 알려져있듯이 쥐프 인코딩 기술에 포함되어 있는 LZW압축 방식이 특허권에 저당잡혀있는터라 공개 쥐프 인코딩 라이브러리는 사실상 무료로 만들기가 난망합니다. 자바계에서는 에크미(Acme)가 이분야에서 유명한데, 안타깝게도 압축률이 거의 제로에 가까울 정도로 "그냥" 인코딩 합니다. 그나마 쥐프를 생성하는 것만으로도 감지덕지지요. 이상하게도 이분야에 상용 자바 쥐프 인코더 제품이 없는데, 혹시 아시는 분은 소개해주세요. 아무튼 그건 그렇고, 요는 쥐프대신 핑을 쓰라는 것입니다. 핑 이미지를 생성해낼 수 있는 인코더는 현재 JDK 1.4의 이미지 I/O에 포함되어 있어 아주 편리하게 사용할 수 있습니다. 자신의 컴에 JDK 1.4(베타1, 2공히)이 깔려있다면 아래 예제를 도전해보세요.
import java.awt.*;
import java.awt.image.*;
import java.io.*;
import java.util.*;
import javax.imageio.*;
import javax.imageio.stream.*;
import javax.swing.*;

public class TestEncodePNG
{
 public static void main(String[] args) throws Exception
 {
 long startTime = System.currentTimeMillis();
 BufferedImage bi = new BufferedImage(80, 50, BufferedImage.TYPE_INT_RGB);
 Graphics2D big = bi.createGraphics();
 Image clip = new ImageIcon("bg.gif").getImage();
 Image girl = new ImageIcon("girl.gif").getImage();
 big.drawImage(clip, 0, 0, null);
 big.drawImage(girl, 20, 3, null);
 File f = new File("encoded.png");
 ImageIO.write(bi, "png", f);
 long endTime = System.currentTimeMillis();
 System.out.println(endTime + " - " + startTime + " = " + (endTime - startTime));
 }
}
이 소스를 예를 들어 e:₩work₩png-special에 저장하고 컴파일 한 후 아래 그림을 같은 디렉토리에 저장하고 나서

java TestEncodePNG으로 실행하면 걸린 시간이 천분의 1초 단위로 나오면서 합성된 그림이 핑으로 생성됩니다. encoded.png을 보면

과 같이 보입니다. 비교 차원에서 이번에는 애크미 쥐프 인코딩 라이브러리(애크미 전체 라이브러리 중 쥐프 인코딩에 필요한 클래스만 제가 따로 모았습니다. 애크미 라이프러리 전체는 500킬로 바이트이지만 쥐프 인코딩에 필요한 클래스만 모으면 15킬로바이트로 아주 컴팩트합니다.)를 써서 쥐프로 똑같은 그림을 생성해보았습니다.
import Acme.JPM.Encoders.*;
import java.awt.*;
import java.awt.image.*;
import java.io.*;
import java.util.*;
import javax.swing.*;

public class TestEncodeGIF
{
 public static void main(String[] args) throws Exception
 {
  long startTime = System.currentTimeMillis();
		
  FileOutputStream fos = new FileOutputStream("encoded.gif");
		
  BufferedImage bi = new BufferedImage(80, 50, BufferedImage.TYPE_INT_RGB);
  Graphics2D big = bi.createGraphics();
  Image clip = new ImageIcon("bg.gif").getImage();
  Image girl = new ImageIcon("girl.gif").getImage();
  big.drawImage(clip, 0, 0, null);
  big.drawImage(girl, 20, 3, null);

  GifEncoder encoder = new GifEncoder(bi, fos);
  encoder.encode();
  fos.close();
    		
  long endTime = System.currentTimeMillis();
  System.out.println(endTime + " - " + startTime + " = " + (endTime - startTime));
 }
}
기본적으로 앞의 소스와 같은 구조이지만 인코더 부분만 살짝 다릅니다. 이 예제를 실행하려면 위에 있는 애크미 쥐프 인코딩 라이브러리를 클래스패스에 잡아줘야합니다. set CLASSPATH=.;e:₩work₩png-special₩acme-gif-encoder.jar 윈도우즈상에서 acme-gif-encoder.jar를 e:₩work에 저장했을 때의 설정 예입니다. 그리고 나서 컴파일하고 실행하면 아래와 같은 그림이 나옵니다.

핑을 인코딩하려면 JDK 1.4가 필요하다고 했는데, 정확히는 이미지 I/O가 필요한 것입니다. 이 이미지 I/O를 충당하는 방법이 하나 더 있는데, 자바 어드밴스트 이미징(Java Advanced Imaging-JAI)를 까는 것입니다. 사실 이미지 I/O는 JAI의 일부였었는데, 많은 개발자들이 JAI의 기능중 각종 이미지 파일 포멧으로 입출력하는 기능을 자바의 기본 API로 추가시켜주기를 바래 JDK 1.4에 이미지 I/O란 장르로 기본 장착되기에 이르렀습니다. 따라서 JAI의 이미지 I/O 기능은 점차 J2SE API쪽으로 몰아주고 자신은 본래 제작 의도였던 고도의 이미지 처리에 무게를 둘 것으로 보입니다. 아무튼 현재까지는 JAI 1.1에서 핑 인코더를 지원하고 있어서 JDK 1.3이상이면 함께 쓸 수 있습니다. 먼저 JAI 1.1를 JDK 1.3이상이 설치된 상태에서 깔고나면, JAI를 통해 핑을 인코딩할 준비가 다 되었습니다.
import java.io.*;
import java.util.*;
import com.sun.media.jai.codec.*;
import javax.media.jai.*;
import javax.swing.*;

public class TestEncodePNGbyJAI
{
 public static void main(String[] args) throws Exception
 {
  long startTime = System.currentTimeMillis();

  BufferedImage bi = new BufferedImage(80, 50, BufferedImage.TYPE_INT_RGB);
  Graphics2D big = bi.createGraphics();
  Image clip = new ImageIcon("bg.gif").getImage();
  Image girl = new ImageIcon("girl.gif").getImage();
  big.drawImage(clip, 0, 0, null);
  big.drawImage(girl, 20, 3, null);

  String filename = "encodedbyjai.png";
  String format = "PNG";

  RenderedOp op = JAI.create("filestore", bi, filename, format);
    		
  long endTime = System.currentTimeMillis();
  System.out.println(endTime + " - " + startTime + " = " + (endTime - startTime));
  System.exit(0);
 }
}
컴파일하고 나서 실행한 결과 그림은 다음과 같습니다.

이제 각각의 성능을 비교해봅시다. 우선 테스트 환경은 팬티엄3 1기가헤르츠, 램 512메가, 그래픽카드는 인텔815보드에 내장된 82810E였습니다. TestEncodePNG on JDK 1.4 beta 2 - 약 832 밀리세컨드 TestEncoderGIF on JDK 1.4 beta 2 - 약 661 밀리세컨드 TestEncoderPNGbyJAI on JDK 1.3.1_01 - 약 1482 밀리세컨드 (밀리세컨드 millisecond = 천분의 1초) 처음 실행시와 그 다음 실행시의 수행 시간이 조금 다르게 나오기도 하는데, 아마도 클래스 로딩을 비롯한 초기화 시간의 차이로 보입니다. 결과를 놓고 보면 묘하게도 애크미 쥐프쪽이 가장 빠른데, 이유는 당연하게도 압축을 거의 안하기 때문입니다. 또한 JDK 1.4에 포함된 이미지 I/O가 JAI의 그것보다 나은 속도를 보여주는 현상을 통해 JAI의 기능이 J2SE로 이전되면서 계속 업그레이드해왔을 것이란 추측을 할 수 있습니다. 그러면 이번에는 생성된 이미지의 용량면을 비교해보죠. TestEncodePNG on JDK 1.4 beta 2 - 1698 바이트 TestEncoderGIF on JDK 1.4 beta 2 - 2237 바이트 TestEncoderPNGbyJAI on JDK 1.3.1_01 - 3011 바이트 이 결과도 상당히 의외인데, JAI의 핑이 가장 용량이 커서 핑의 우수한 압축력을 무색케해버렸습니다. 다행이 JDK 1.4의 핑은 최소 용량으로 체면을 세웠고 압축을 거의 안한다는 애크미의 쥐프는 그럭저럭한 용량을 보여주었습니다. 결론적으로 핑을 생성하는 데 있어서는 JDK 1.4가 속도, 용량 양면에서 압승을 거두었습니다. 그러나 현실적으로는 JDK 1.3에서도 써야할 지 모르므로 JAI도 염두에 두시고, 어쩔 수 없이 쥐프를 쓰셔야하는 분은 애크미를 잘 활용하시기 바랍니다. (참고로 JDK 1.4에서 지원하는 포멧은 GIF, PNG, JPG로서, 디코딩-인코딩 양쪽 다 지원합니다. 한마디 읽고쓰기 다 된다는 말씀.) 예제 작성에 도움준 문헌아 참! JDK 1.1, 1.2를 쓰시는 분들을 위한 JIMI에도 핑 인코더가 있어요. 원하시는 분이 있으면 언제 소개해보죠. (근데 요새 JDK 1.1을 쓰는 사람이 있던가... 1년전만해도 현역이었었는데...)
TAG :
댓글 입력
자료실

최근 본 책0